package edu.se.jai.websocketgateway.service;

import edu.se.jai.openfeignapi.dto.*;
import edu.se.jai.openfeignapi.feign.GameServiceFeignApi;
import edu.se.jai.websocketgateway.dto.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * 消息发送服务
 * 
 * 负责发送各种WebSocket消息，包括：
 * - 点对点消息：发送给特定用户
 * - 房间广播消息：发送给房间内所有玩家
 * - 全局广播消息：发送给所有在线用户
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MessageSendService {

    private final SimpMessagingTemplate messagingTemplate;

    /**
     * 通知连接消息
     */
    public void notifyConnect(String playerName, String sessionId, boolean success, String info) {
        WebSocketMessage message = new WebSocketMessage();
        message.setType(MessageType.CONNECT_RESPONSE);

        ConnectData responseData = new ConnectData(playerName, sessionId, success, info);
        message.setData(responseData);
        log.info("玩家 {} 连接，{}", playerName, success);

        // 发送响应给指定用户
        messagingTemplate.convertAndSend("/queue/response-user" + sessionId, message);
    }

    /**
     * 通知房间创建消息
     */
    public void notifyCreate(GameRoomDto room, String sessionId) {
        WebSocketMessage message = new WebSocketMessage();
        message.setType(MessageType.ROOM_CREATE);
        message.setData(room);

        // 发送给创建者
        String userDestination = "/queue/response-user" + sessionId;
        messagingTemplate.convertAndSend(userDestination, message);
        log.info("发送创建房间响应: sessionId={}, roomId={}", sessionId, room.getRoomId());

        // 创建房间也是房间更新，广播给所有玩家
        notifyRoomUpdate(room);
    }

    /**
     * 通知房间加入消息
     */
    public void notifyJoin(GameRoomDto room, String sessionId) {
        WebSocketMessage message = new WebSocketMessage();
        message.setType(MessageType.ROOM_JOIN);
        message.setData(room);
        
        log.info("玩家 {} 加入房间 {}，当前房间人数: {}", sessionId, room.getRoomId(), room.getPlayers().size());
        
        // 发送给加入的玩家自己
        String userDestination = "/queue/response-user" + sessionId;
        messagingTemplate.convertAndSend(userDestination, message);
        
        // 发送给房间内其他玩家
        messagingTemplate.convertAndSend("/room/" + room.getRoomId(), message);
    }

    /**
     * 通知房间离开消息
     */
    public void notifyLeave(GameRoomDto room, String sessionId) {
        WebSocketMessage message = new WebSocketMessage();
        message.setType(MessageType.ROOM_LEAVE);
        message.setData(room);
        
        log.info("玩家 {} 离开房间 {}，当前房间人数: {}", sessionId, room.getRoomId(), room.getPlayers().size());
        
        // 发送给房间内其他玩家
        messagingTemplate.convertAndSend("/room/" + room.getRoomId(), message);
    }

    /**
     * 通知房间被解散
     */
    public void notifyRoomDissolved(GameRoomDto room) {
        WebSocketMessage message = new WebSocketMessage();
        message.setType(MessageType.ROOM_DISSOLVE);
        message.setData(room);

        // 广播给所有订阅了房间列表的玩家
        messagingTemplate.convertAndSend("/topic/roomUpdate", message);
        log.info("已广播房间解散通知: {}", room.getRoomId());
    }

    /**
     * 通知房间更新
     */
    public void notifyRoomUpdate(GameRoomDto room) {
        WebSocketMessage message = new WebSocketMessage();
        message.setType(MessageType.ROOM_UPDATE);
        message.setData(room);

        // 发送给房间内所有玩家
        messagingTemplate.convertAndSend("/room/" + room.getRoomId(), message);
        log.info("已通知房间 {} 更新，当前房间人数: {}", room.getRoomId(), room.getPlayers().size());

        // 广播房间更新给所有玩家
        messagingTemplate.convertAndSend("/topic/roomUpdate", message);
        log.info("已广播房间 {} 更新通知，当前房间人数: {}", room.getRoomId(), room.getPlayers().size());
    }

    /**
     * 发送错误消息给指定用户
     */
    public void notifyErrorMessage(String sessionId, String errorMessage) {
        WebSocketMessage response = new WebSocketMessage();
        response.setType(MessageType.ERROR);
        response.setData(errorMessage);
        log.info("发送ERROR响应: sessionId={}, content={}", sessionId, errorMessage);
        
        String userDestination = "/queue/response-user" + sessionId;
        messagingTemplate.convertAndSend(userDestination, response);
        log.info("已发送ERROR响应到用户: {}", sessionId);
    }

    /**
     * 发送所有房间列表
     */
    public void notifyAllRooms(List<GameRoomDto> rooms, String sessionId) {
        WebSocketMessage response = new WebSocketMessage();
        response.setType(MessageType.ROOMS_LIST);
        
        response.setData(rooms);
        log.info("发送ALL_ROOMS_LIST响应: sessionId={}, {} 个房间", sessionId, rooms.size());
        
        String userDestination = "/queue/response-user" + sessionId;
        messagingTemplate.convertAndSend(userDestination, response);
        log.info("已发送ALL_ROOMS_LIST响应到用户: {}", sessionId);
    }

    // ==================== 游戏相关消息发送方法 ====================

    /**
     * 通知游戏开始
     */
    public void notifyGameStart(GameRoomDto room) {
        WebSocketMessage message = new WebSocketMessage();
        message.setType(MessageType.GAME_START);
        message.setData(room);

        // 发送给房间内所有玩家
        messagingTemplate.convertAndSend("/room/" + room.getRoomId(), message);
        log.info("已通知房间 {} 游戏开始", room.getRoomId());

        // 广播房间更新给所有玩家
        notifyRoomUpdate(room);
    }

    /**
     * 通知游戏停止
     */
    public void notifyGameStop(GameRoomDto room) {
        WebSocketMessage message = new WebSocketMessage();
        message.setType(MessageType.GAME_STOP);
        message.setData(room);

        // 发送给房间内所有玩家
        messagingTemplate.convertAndSend("/room/" + room.getRoomId(), message);
        log.info("已通知房间 {} 游戏停止", room.getRoomId());

        // 广播房间更新给所有玩家
        notifyRoomUpdate(room);
    }

    /**
     * 通知猜测结果
     * 
     * 发送两种类型的GUESS_RESULT消息：
     * 1. 个人反馈：发送给猜测者自己，包含详细提示和UI状态更新
     * 2. 公开信息：发送给房间内其他玩家，显示公开的猜测信息
     */
    public void notifyGuessResult(String roomId, String playerName, Integer guess, Boolean result, String hint, String sessionId) {
        // 1. 发送个人反馈给猜测者
        WebSocketMessage personalMessage = new WebSocketMessage();
        personalMessage.setType(MessageType.GUESS_RESULT);
        GuessResult personalResult = GuessResult.createPersonalResult(roomId, playerName, guess, result, hint);
        personalMessage.setData(personalResult);
        messagingTemplate.convertAndSend("/queue/response-user" + sessionId, personalMessage);
        log.info("已发送个人反馈给 {}: {}", playerName, hint);
        
        // 2. 发送公开信息给房间内其他玩家
        WebSocketMessage publicMessage = new WebSocketMessage();
        publicMessage.setType(MessageType.GUESS_RESULT);
        GuessResult publicResult = GuessResult.createPublicResult(roomId, playerName, guess, result);
        publicMessage.setData(publicResult);
        messagingTemplate.convertAndSend("/room/" + roomId, publicMessage);
        log.info("已发送公开信息到房间 {}: {}", roomId, publicResult.getMessage());
    }
}

